<template>
  <el-upload v-bind="$attrs" :auto-upload="false" v-model:file-list="fileList" :accept="props.accept" :action="'#'"
    multiple :on-preview="handlePreview" :on-remove="handleRemove" :before-remove="handleBeforeRemove"
    :limit="props.limit" :on-exceed="handleExceed" :on-change="handleChange" :on-success="handleSuccess"
    :on-error="handleError" :before-upload="handleBeforeUpload" :show-file-list="false">
    <!-- 上传触发的插槽 -->
    <slot></slot>
    <!-- 提示说明文字的插槽 -->
    <template #tip>
      <slot name="tip"></slot>
    </template>
  </el-upload>

  <!-- 传输的文件列表 -->
  <div v-if="fileList.length > 0" class="mt-10px isLeft10">
    <div>
      <div v-for="item in fileList" :key="item.url" class="flex mb-5px align-center justify-between">
        <esTooltip :content="item.name" :className="['text-14px text-606']"></esTooltip>
        <div class="flex align-center">
          <div class="upload-remove upload-box" @click="onRemoveClick(item)">删除</div>
          <div class="upload-download  upload-box" @click="onDownloadClick(item)" v-if="props.isShowOperateButtons">下载
          </div>
          <div class="upload-preview  upload-box" v-if="isPreview(item) && props.isShowOperateButtons"
            @click="onPreviewClick(item)">预览</div>
        </div>
      </div>
    </div>
  </div>

  <!-- 图片展示组件 -->
  <el-image-viewer v-if="dialogVisible" @close="onCloseViewerClick" :url-list="urlList" :initial-index="initialIndex" />
  <!-- 文件展示组件 -->
  <vueOffice v-model="vueOfficeUrl"></vueOffice>
</template>
<script lang="ts" setup>
import callApi from "@/axios/index.ts";
import { debounce, fileSuffixTypeUtil } from "@/utils/logicalTools/utils.ts";
import { watch, ref } from "vue";
import { ElMessage, ElMessageBox } from "element-plus";
import type { UploadProps } from "element-plus";
import esTooltip from "@/components/esTooltip.vue";

let props = defineProps({
  modelValue: [String, Object, Array], //文件列表
  data: { // 上传的请求参数
    type: Object,
    default: () => { },
  },
  action: {// 接口地址
    type: String,
    default: "/oss/files/uploadWareHouse",
  },
  limit: { // 数量限制
    type: Number,
    default: 1000,
  },
  fileSize: { // 大小限制(MB)
    type: Number,
    default: 5000,
  },
  accept: { // 文件类型
    type: String,
    default: "",
  },
  isShowTip: { // 是否显示提示
    type: Boolean,
    default: true,
  },
  disabledAutoUpload: { // 禁止自动上传
    type: Boolean,
    default: false,
  },
  isShowOperateButtons: { // 是否显示列表中文件操作按钮
    type: Boolean,
    default: true,
  },
});

let emit = defineEmits([
  "update:modelValue",
  "before-remove",
  "on-remove",
  "on-preview",

  "on-change",
  "on-success",
  "upload-success",
  "upload-error",
  "on-error",
  "before-upload",
  "on-upload-success",
  "on-upload-error",
]);

let fileList = ref([]); // 文件列表
let dialogVisible = ref(false); // 图片文件预览
let urlList = ref([]); // 预览图片列表
let initialIndex = ref(0); // 初始化图片预览索引位置
let vueOfficeUrl = ref({ // 文件预览信息对象
  name: "",
  url: "",
});

watch(
  () => props.modelValue,
  (val: any[]) => {
    if (val.length) {
      console.log(val);
      let temp = 1;
      // 然后将数组转为对象数组
      fileList.value = val.map((item) => {
        item = { name: item.name, url: item.url || "" };
        item.uid = item.uid || new Date().getTime() + temp++;
        return item;
      });
    } else {
      fileList.value = [];
      return [];
    }
  },
  { deep: true, immediate: true }
);



// 文件列表移除时的处理
const handleRemove: UploadProps["onRemove"] = (file, uploadFiles) => {
  console.log(file, uploadFiles);
  emit("on-remove", file, uploadFiles); // 文件移除回调
};



// 在超出选中文件数量时的处理
const handleExceed: UploadProps["onExceed"] = (files, uploadFiles) => {
  ElMessage.warning(
    `最多选择${props.limit}个文件,你已经选择了${files.length}个文件`
  );
};


// 上传成功
const handleSuccess: UploadProps["onSuccess"] = (
  response,
  uploadFile,
  uploadFiless
) => {
  console.log(response, uploadFile, uploadFiless, "onSuccess");
  emit("on-success", response, uploadFile, uploadFiless);
};

// 上传失败
const handleError: UploadProps["onError"] = (
  error,
  uploadFile,
  uploadFiles
) => {
  console.log(error, uploadFile, uploadFiles, "onError");
  emit("on-error", error, uploadFile, uploadFiles);
};

// 上传时的处理
const handleChange: UploadProps["onChange"] = async (rawFile, uploadFiles) => {
  console.log(rawFile, "handleChange");

  if (rawFile.size > 1024 * 1024 * props.fileSize) {
    ElMessage.error("文件过大，请重新上传");
    fileList.value.splice(fileList.value.length - 1, 1);
    return;
  }
  if (!props.disabledAutoUpload) {
    getOssFileUpload();
  }
  emit("on-change", rawFile, uploadFiles);
};

// 上传前的处理
const handleBeforeUpload: UploadProps["beforeUpload"] = (rawFile) => {
  console.log(rawFile, "handleBeforeUpload");
  return false;
};

// 关闭图片预览
const onCloseViewerClick = () => {
  dialogVisible.value = false;
};

// 上传
const getOssFileUpload = debounce(() => {
  let param = new FormData();
  for (let i = 0; i < fileList.value.length; i++) {
    if (fileList.value[i].raw) {
      param.append(`file`, fileList.value[i].raw);
    }
  }

  props.data &&
    Object.keys(props.data).forEach((k) => {
      param.append(k, props.data[k]);
    });

  return callApi({
    api: props.action,
    param: param,
    config: {
      headers: {
        "Content-Type": "multipart/form-data; charset=UTF-8",
      },
    },
  })
    .then((res) => {
      if (Array.isArray(res.data)) {
        console.log(res.data, 'res.data')
        res.data?.forEach((item, index) => {
          const { url } = item.data;
          const fileIndex = fileList.value.length - res.data.length + index;
          fileList.value[fileIndex].url = url;
          // fileList.value[fileIndex].url = encodeSearchKey(url);
        });
      }
      console.log(fileList.value, "res");
      emit("update:modelValue", fileList.value || []);
      emit("upload-success");
    })
    .catch((error) => {
      emit("upload-error");
    });
}, 500);

// 对查询关键字中的特殊字符进行编码
function encodeSearchKey(key) {
  const encodeArr = [
    {
      code: "%",
      encode: "%25",
    },
    {
      code: "?",
      encode: "%3F",
    },
    {
      code: "#",
      encode: "%23",
    },
    {
      code: "&",
      encode: "%26",
    },
    {
      code: "=",
      encode: "%3D",
    },
    {
      code: " ",
      encode: "%20",
    },
    {
      code: "/",
      encode: "%2F",
    },
    {
      code: ":",
      encode: "%3A",
    },
    {
      code: ";",
      encode: "%3B",
    },
    {
      code: ",",
      encode: "%2C",
    },
  ];
  return key.replace(/[%?#&=]/g, ($, index, str) => {
    for (const k of encodeArr) {
      if (k.code === $) {
        return k.encode;
      }
    }
  });
}


// 自定义删除
const onRemoveClick = (item) => {
  handleBeforeRemove(item);
};

// 文件列表-删除提示
const handleBeforeRemove: UploadProps["beforeRemove"] = (
  uploadFile,
  uploadFiles
) => {
  console.log(uploadFile, uploadFiles, fileList.value, "fileList.value");

  console.log(uploadFile, uploadFiles);
  return ElMessageBox.confirm(`是否删除${uploadFile.name} ?`).then(
    () => {
      const index = fileList.value.findIndex((item) => {
        return item.uid === uploadFile.uid;
      });
      fileList.value.splice(index, 1);
      emit("update:modelValue", fileList.value);
      ElMessage.success("删除成功");
      return true;
    },
    () => {
      return false;
    }
  );
};

// 自定义下载
const onDownloadClick = (item) => {
  console.log(item.url, 'url');

  window.open(item.url);
};

// 自定义预览
const onPreviewClick = (item) => {
  handlePreview(item);
};

// 文件预览
const handlePreview: UploadProps["onPreview"] = (uploadFile) => {
  console.log(uploadFile, "handlePreview");

  const fileSuffixTypeUtilType = fileSuffixTypeUtil.matchFileSuffixType(
    uploadFile.name
  );
  console.log(fileSuffixTypeUtilType, 'fileSuffixTypeUtilType');

  // 是图片时展开预览
  if (fileSuffixTypeUtilType == "image") {
    urlList.value = [];
    console.log(fileList.value, 'fileList.value');

    fileList.value.forEach((v, i) => {
      if (v.url === uploadFile.url) {
        initialIndex.value = i;
      }
      console.log(v, v.name, ' fileList.value');

      if ((fileSuffixTypeUtil.matchFileSuffixType(v.name) == "image") || (fileSuffixTypeUtil.matchFileSuffixType(v.url) == "image")) {
        urlList.value.push(v.url);
      }
    });
    dialogVisible.value = true;
    console.log(urlList.value, 'urlList.value');
  }

  if (["xls", "doc"].includes(fileSuffixTypeUtilType)) {
    return ElMessage.warning(`暂不支持在线预览.${fileSuffixTypeUtilType}文件`);
  }
  if (
    ["excel", "xlsx", "word", "docx", "pdf"].includes(fileSuffixTypeUtilType)
  ) {
    vueOfficeUrl.value = {
      name: uploadFile.name,
      url: uploadFile.url,
    };
  }
  emit("on-preview", uploadFile); // 文件预览回调
};

// 是否显示预览
const isPreview = (item) => {
  const fileSuffixTypeUtilType = fileSuffixTypeUtil.matchFileSuffixType(
    item.name
  );
  console.log(fileSuffixTypeUtilType, "fileSuffixTypeUtilType");

  if (fileSuffixTypeUtilType == "image") {
    return true;
  }
  if (["xls", "doc"].includes(fileSuffixTypeUtilType)) {
    return false;
  }
  if (
    ["excel", "xlsx", "word", "docx", "pdf"].includes(fileSuffixTypeUtilType)
  ) {
    return true;
  }
};

defineExpose({ getOssFileUpload });
</script>

<style scoped lang="scss">
.isLeft10 {
  margin-left: 10%
}

.text-606 {
  color: #606266;
}

.upload {
  &-box {
    color: var(--el-color-primary);
    font-size: 14px;
    width: 35px;
    cursor: pointer;
    text-align: center;
  }

  &-download {}

  &-preview {}

  &-remove {
    color: red;
  }
}
</style>
